package cn.org.xwb.bookmall.admin.controller;

import cn.org.xwb.bookmall.admin.service.LoginService;
import cn.org.xwb.bookmall.model.constant.AccountConst;
import cn.org.xwb.bookmall.model.mapper.ManagerMapper;
import cn.org.xwb.bookmall.model.po.Manager;
import cn.org.xwb.bookmall.model.service.impl.AllowMailServiceImpl;
import cn.org.xwb.bookmall.model.utils.BookRedisUtil;
import cn.org.xwb.bookmall.model.vo.ManagerVo;
import cn.org.xwb.bookmall.model.vo.UserVo;
import cn.org.xwb.common.encrypt.annotation.des.DesEn;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDe;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDeParam;
import cn.org.xwb.common.encrypt.constant.EncryptConstant;
import cn.org.xwb.common.encrypt.utils.SHAUtil;
import cn.org.xwb.common.error.annotation.ServerErrorCatch;
import cn.org.xwb.common.mail.annotation.IsMail;
import cn.org.xwb.common.mail.annotation.IsMailParam;
import cn.org.xwb.common.mail.utils.MailUtil;
import cn.org.xwb.common.model.vo.RespResult;
import cn.org.xwb.common.valid.annotation.str.StrNotNull;
import cn.org.xwb.common.valid.annotation.str.StrNotNullParam;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Objects;

@RestController
@RequestMapping("/login")
public class LoginController {

    @Autowired
    private LoginService loginService;

    @GetMapping("/mail/code")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    @IsMail
    public RespResult<Object> getMailCode(
            @RequestParam("mail")
            @StrNotNullParam @RsaDeParam @IsMailParam
            String mail
    ) {
        return loginService.sendMailCode(mail);
    }

    @PostMapping("/mail")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    @IsMail
    public RespResult<Object> loginByMail(
            @RequestParam("mail")
            @StrNotNullParam @RsaDeParam @IsMailParam
            String mail,
            @RequestParam("code")
            @StrNotNullParam @RsaDeParam
            String code
    ) {
        return loginService.loginByMail(mail, code);
    }

    @Autowired
    private ManagerMapper managerMapper;

    @Autowired
    private BookRedisUtil bookRedisUtil;

    @Autowired
    private MailUtil mailUtil;

    @Autowired
    private AllowMailServiceImpl allowMailService;

    @PostMapping("/pwd")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    @DesEn
    public RespResult<Object> loginByPwd(
            @RequestParam(EncryptConstant.DES_KEY_PARAM_NAME) @StrNotNullParam @RsaDeParam
            String desKey,
            @RequestParam("account")
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam("pwd")
            @StrNotNullParam @RsaDeParam
            String pwd
    ) {
        if (mailUtil.mailIsLegal(account)) {
            // 判断该邮箱是否可以登录管理端
            Boolean judgeRes = allowMailService.judgeAllow(account);
            if (Objects.isNull(judgeRes)) return RespResult.fail("系统发生异常，请刷新页面或稍后尝试");
            if (!judgeRes) return RespResult.fail("该邮箱无权登录管理端");
        }
        LambdaQueryWrapper<Manager> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Manager::getMail, account)
                .or().eq(Manager::getAccount, account)
                .or().eq(Manager::getUsername, account);
        Manager manager = managerMapper.selectOne(wrapper);
        if (Objects.isNull(manager)) return RespResult.fail("抱歉，您暂时无权进行登录");
        if (manager.getDisabled()) return RespResult.fail("抱歉，您暂时无权进行登录");
        Boolean verify = SHAUtil.encryptionVerifyBySHA256(pwd, manager.getSalt(), manager.getPwd());
        if (!verify) return RespResult.fail("账号或密码错误");
        // 缓存账号信息
        // 失败
        if (!bookRedisUtil.cacheManager(manager)) return RespResult.fail("系统发生异常，请刷新页面或稍后重试");
        // 登录成功
        // 返回账号信息
        return RespResult.success("登录成功", new ManagerVo(manager));
    }

    /**
     * 登录是否有效
     *
     * @param account
     * @return
     */
    @GetMapping("/effective")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    public RespResult<Object> effetive(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account
    ) {
        return loginService.effective(account);
    }

}
